import {
  Catch,
  HttpException,
  ExceptionFilter,
  ArgumentsHost,
  Inject,
  HttpStatus,
} from '@nestjs/common';
import { RVo } from '../utils/result.vo';
import { QueryFailedError } from 'typeorm';
import { isString } from '../utils/tool';
import { Logger } from '../logger/logger.service';

@Catch()
export class CustomExceptionFilter implements ExceptionFilter {
  @Inject(Logger)
  private logger: Logger;

  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();
    let status = HttpStatus.INTERNAL_SERVER_ERROR;
    let excRes: string | object = 'Internal server error';

    if (exception instanceof HttpException) {
      status = exception.getStatus();
      excRes = exception.getResponse();
    } else if (exception instanceof QueryFailedError) {
      excRes = exception.message;
    } else if (exception instanceof Error) {
      excRes = exception.message;
    } else if (typeof exception === 'object' && exception !== null) {
      excRes = exception;
    }

    let resDto: RVo<null>;
    if (isString(excRes)) {
      resDto = new RVo({ code: status, data: null, msg: excRes });
    } else {
      const RVoMsg = {
        ...(excRes as Record<string, any>),
      };
      if ((excRes as Record<string, any>).message) {
        RVoMsg.msg = Array.isArray((excRes as Record<string, any>).message)
          ? (excRes as Record<string, any>).message.join(',')
          : (excRes as Record<string, any>).message;
      }

      resDto = new RVo({
        code: status,
        data: null,
        ...RVoMsg,
      });
    }

    const logFormat = `
    ##############################################################################################################
    Request original url: ${request.originalUrl}
    Method: ${request.method}
    UserAgent: ${request.headers['user-agent']}
    IP: ${request.ip}
    User: ${request.user?.userId}
    Status code: ${status}
    Response: ${resDto.msg}
    ##############################################################################################################
    `;
    this.logger.error(logFormat, 'HttpException filter ');
    response.status(200).json(resDto);
  }
}
